package online.heycm.rbac.common.uid;

import online.heycm.platform.common.entity.exception.Assert;
import online.heycm.platform.common.entity.result.Optional;
import online.heycm.rbac.domain.basic.repository.IdGeneratorRepository;
import online.heycm.rbac.domain.basic.repository.entity.BasicGeneratorIds;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 序列ID服务实现
 *
 * @author hey
 * @version 1.0
 * @date 2024/1/16 17:48
 */
@Component
public class UidServiceImpl implements UidService {

    private final Map<String, AtomicLong> uidCache = new ConcurrentHashMap<>();
    private final Map<String, Long> uidMaxCache = new ConcurrentHashMap<>();

    @Autowired
    private IdGeneratorRepository idGeneratorRepository;

    @Override
    public long nextId(String idKey) {
        AtomicLong uid = uidCache.get(idKey);
        Long uidMax = uidMaxCache.get(idKey);
        if (uid == null || uid.get() >= uidMax) {
            synchronized (this) {
                uid = uidCache.get(idKey);
                uidMax = uidMaxCache.get(idKey);
                if (uid == null || uid.get() >= uidMax) {
                    Optional<BasicGeneratorIds> optional = idGeneratorRepository.acquireId(idKey);
                    Assert.require(optional);
                    BasicGeneratorIds generatorIds = optional.get();
                    uidMax = generatorIds.getIdValue() + generatorIds.getIdStep();
                    uid = new AtomicLong(generatorIds.getIdValue());
                    uidMaxCache.put(idKey, uidMax);
                    uidCache.put(idKey, uid);
                    return uid.getAndIncrement();
                }
            }
        }
        return uid.getAndIncrement();
    }


}
